package helper

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"math"
	"math/rand"
	"strings"
	"time"

	"github.com/fatih/structs"
	"github.com/google/uuid"
	"github.com/gookit/color"
	"github.com/jinzhu/copier"
)

var allRandomStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func init() {
	rand.New(rand.NewSource(time.Now().UnixNano()))
}

func RandomString(length int) string {
	byteList := make([]byte, length)
	for i := 0; i < length; i++ {
		byteList[i] = allRandomStr[rand.Intn(62)]
	}
	return string(byteList)
}

func MakeUuid() string {
	return strings.ReplaceAll(uuid.New().String(), "-", "")
}

func MakeMd5(data string) string {
	sum := md5.Sum([]byte(data))
	return hex.EncodeToString(sum[:])
}

func Round(val float64, n int) float64 {
	base := math.Pow(10, float64(n))
	return math.Round(base*val) / base
}

func FormatTimestamp(timestamp int64, types string) string {
	temp := time.Unix(timestamp, 0)

	format := "2006-01-02 15:04:05"
	if types == "date" {
		format = "2006-01-02"
	}

	return temp.Format(format)
}

func JsonToObj(jsonStr string, toVal any) (err error) {
	if err = json.Unmarshal([]byte(jsonStr), &toVal); err != nil {
		color.Red.Println("JsonToObj失败: " + err.Error())
		panic("系统错误")
	}
	return
}

func ObjToJson(data any) string {
	b, err := json.Marshal(data)
	if err != nil {
		color.Red.Println("ObjToJson失败: " + err.Error())
		panic("系统错误")
	}
	return string(b)
}

func StructsToMaps(obj any) []map[string]any {
	var objList []any
	err := copier.Copy(&objList, obj)
	if err != nil {
		color.Red.Println("StructsToMaps失败: " + err.Error())
		panic("系统错误")
	}
	var data []map[string]any
	for _, v := range objList {
		data = append(data, structs.Map(v))
	}
	return data
}

func Copy(toValue any, fromValue any) {
	if err := copier.Copy(toValue, fromValue); err != nil {
		color.Red.Println("copy失败: " + err.Error())
		panic("系统错误")
	}
}

func ListToTree(arr []map[string]any, id string, pid string, child string) (mapList []any) {
	mapList = []any{}
	idValMap := make(map[string]any)
	for _, m := range arr {
		if idVal, ok := m[id]; ok {
			idValMap[idVal.(string)] = m
		}
	}
	for _, m := range arr {
		if pidVal, ok := m[pid]; ok {
			if pNode, pok := idValMap[pidVal.(string)]; pok {
				if cVal, cok := pNode.(map[string]any)[child]; cok {
					if cVal == nil {
						cVal = []any{m}
					} else {
						cVal = append(cVal.([]any), m)
					}
					pNode.(map[string]any)[child] = cVal
					continue
				}
			}
		}
		mapList = append(mapList, m)
	}
	return
}
